//*****************************************************************************
//
// cmdline.c - Functions to help with processing command lines.
//
// Copyright (c) 2007 Luminary Micro, Inc.  All rights reserved.
// 
// Software License Agreement
// 
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
// 
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  Any use in violation
// of the foregoing restrictions may subject the user to criminal sanctions
// under applicable laws, as well as to civil liability for the breach of the
// terms and conditions of this license.
// 
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 1716 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup utilities_api
//! @{
//
//*****************************************************************************

#include <string.h>
#include "cmdline.h"

//*****************************************************************************
//
// Defines the maximum number of arguments that can be parsed.
//
//*****************************************************************************
#define MAX_ARGS                8

//*****************************************************************************
//
//! Process a command line string into args and execute the command.
//!
//! \param pcCmdLine points to a string that contains a command line
//! that was obtained by an application by some means.
//!
//! This function will take the supplied command line string and break
//! it up into individual arguments.  The first argument is treated as
//! a command and is searched for in the command table.  If the command
//! is found, then the command function is called and all of the command
//! line arguments are passed in the normal argc, argv form.
//!
//! The command table is contained in an array named g_sCmdTable which must
//! be implemented in the application.
//!
//! This function is contained in <tt>utils/cmdline.c</tt>, with
//! <tt>utils/cmdline.h</tt> containing the API definition for use by
//! applications.
//!
//! \return CMDLINE_BAD_CMD if the command is not found, CMDLINE_TOO_MANY_ARGS
//! if there are more args than can be parsed.  Otherwise it returns
//! the code that was returned by the command function.
//
//*****************************************************************************
int
CmdLineProcess(char *pcCmdLine)
{
    static char *argv[10];
    char *pcChar;
    int argc;
    int bFindArg = 1;
    tCmdLineEntry *pCmdEntry;

    //
    // Initialize the argument counter, and point to the beginning of
    // the command line string.
    //
    argc = 0;
    pcChar = pcCmdLine;

    //
    // Advance through the command line until a zero character is found.
    //
    while(*pcChar)
    {
        //
        // If there is a space, then replace it with a zero, and set
        // the flag to search for the next argument.
        //
        if(*pcChar == ' ')
        {
            *pcChar = 0;
            bFindArg = 1;
        }

        //
        // Otherwise it is not a space, so it must be a character that
        // is part of an argument.
        //
        else
        {
            //
            // If bFindArg is set, then that means we are looking for the
            // start of the next argument.
            //
            if(bFindArg)
            {
                //
                // As long as the maximum number of arguments has not
                // been reached, then save the pointer to the start of this
                // new arg in the argv array, and increment the count of
                // args, argc.
                //
                if(argc < MAX_ARGS)
                {
                    argv[argc] = pcChar;
                    argc++;
                    bFindArg = 0;
                }

                //
                // The maximum number of arguments has been reached so
                // return the error.
                //
                else
                {
                    return(CMDLINE_TOO_MANY_ARGS);
                }
            }
        }

        //
        // Advance to the next character in the command line.
        //
        pcChar++;
    }

    //
    // If one or more arguments was found, then process the command.
    //
    if(argc)
    {
        //
        // Start at the beginning of the command table, to look for
        // a matching command.
        //
        pCmdEntry = &g_sCmdTable[0];

        //
        // Search through the command table until a null command string
        // is found, which marks the end of the table.
        //
        while(pCmdEntry->pcCmd)
        {
            //
            // If this command entry command string matches argv[0],
            // then call the function for this command, passing the
            // command line arguments.
            //
            if(!strcmp(argv[0], pCmdEntry->pcCmd))
            {
                return(pCmdEntry->pfnCmd(argc, argv));
            }

            //
            // Not found, so advance to the next entry.
            //
            pCmdEntry++;
        }
    }

    //
    // Fall through to here means that no matching command was found,
    // so return an error.
    //
    return(CMDLINE_BAD_CMD);
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
